package com.empire.framework.security.core.service;

import com.empire.framework.common.encrypt.*;
import com.empire.framework.common.util.crypto.Sm3Util;
import lombok.extern.slf4j.Slf4j;

import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 加解密接口模拟工具类
 * 用于测试环境，模拟第三方加解密接口的返回结果
 */
@Slf4j
public class MockCryptoUtil {

    // 用于存储加密时生成的随机数，解密时需要验证
    private static final Map<String, String> ENCRYPT_CACHE = new HashMap<>();
    private static final SecureRandom RANDOM = new SecureRandom();
    // 固定加密类型
    public static final String ENCRYPT_KEY_TYPE = "33";
    /**
     * 模拟加密接口
     */
    public static EncryptResponse encrypt(String plaintext) {
        try {
            // 模拟网络延迟
            simulateNetworkDelay();

            // 生成随机数
            String pucRandom = generateRandomString(16);

            // 模拟加密过程：实际项目中可以使用真实的加密算法
            String ciphertext = mockEncrypt(plaintext, pucRandom);

            // 缓存随机数，用于解密验证
            ENCRYPT_CACHE.put(ciphertext, pucRandom);
            // 限制缓存大小，防止内存溢出
            if (ENCRYPT_CACHE.size() > 1000) {
                ENCRYPT_CACHE.remove(ENCRYPT_CACHE.keySet().iterator().next());
            }

            // 构建成功响应
            EncryptResponse response = new EncryptResponse();
            response.setSuccess("true");
            response.setErrorCode("0");
            response.setErrorMsg("success");

            EncryptData data = new EncryptData();
            data.setCiphertext(ciphertext);
            data.setPucRandom(pucRandom);
            response.setData(data);

            return response;
        } catch (Exception e) {
            log.error("模拟加密失败", e);
            EncryptResponse errorResponse = new EncryptResponse();
            errorResponse.setSuccess("false");
            errorResponse.setErrorCode("9999");
            errorResponse.setErrorMsg("加密失败: " + e.getMessage());
            return errorResponse;
        }
    }

    /**
     * 模拟解密接口
     */
    public static DecryptResponse decrypt(DecryptRequest request) {
        try {
            // 模拟网络延迟
            simulateNetworkDelay();

            // 验证随机数是否匹配
            String cachedRandom = ENCRYPT_CACHE.get(request.getPlainText());
            if (cachedRandom == null || !cachedRandom.equals(request.getPucRandom())) {
                DecryptResponse errorResponse = new DecryptResponse();
                errorResponse.setSuccess("false");
                errorResponse.setErrorCode("1001");
                errorResponse.setErrorMsg("随机数不匹配，解密失败");
                return errorResponse;
            }

            // 模拟解密过程
            String plaintext = mockDecrypt(request.getPlainText(), request.getPucRandom());

            // 构建成功响应
            DecryptResponse response = new DecryptResponse();
            response.setSuccess("true");
            response.setErrorCode("0");
            response.setErrorMsg("success");
            response.setData(plaintext);

            return response;
        } catch (Exception e) {
            log.error("模拟解密失败", e);
            DecryptResponse errorResponse = new DecryptResponse();
            errorResponse.setSuccess("false");
            errorResponse.setErrorCode("9999");
            errorResponse.setErrorMsg("解密失败: " + e.getMessage());
            return errorResponse;
        }
    }

    /**
     * 模拟完整性验证接口
     */
    public static IntegrityVerifyResponse verifyIntegrity(IntegrityVerifyRequest request) {
        try {
            // 模拟网络延迟
            simulateNetworkDelay();

            log.info("模拟完整性验证，明文长度: {}", request.getPlainText() != null ? request.getPlainText().length() : 0);

            // 模拟生成签名：实际项目中可以使用真实的签名算法
            String signature = generateSignature(request.getPlainText());

            // 构建成功响应
            IntegrityVerifyResponse response = new IntegrityVerifyResponse();
            response.setSuccess("true");
            response.setErrorCode("0");
            response.setErrorMsg("success");
            response.setData(signature);

            return response;
        } catch (Exception e) {
            log.error("模拟完整性验证失败", e);
            IntegrityVerifyResponse errorResponse = new IntegrityVerifyResponse();
            errorResponse.setSuccess("false");
            errorResponse.setErrorCode("9999");
            errorResponse.setErrorMsg("完整性验证失败: " + e.getMessage());
            return errorResponse;
        }
    }

    /**
     * 模拟加密过程
     */
    private static String mockEncrypt(String plaintext, String random) {
        if (plaintext == null) {
            return null;
        }

        // 简单的模拟加密：实际项目中可以替换为真实的加密算法
        String combined = plaintext + "|" + random;
        return Base64.getEncoder().encodeToString(combined.getBytes(StandardCharsets.UTF_8));
    }

    /**
     * 模拟解密过程
     */
    private static String mockDecrypt(String ciphertext, String random) {
        if (ciphertext == null) {
            return null;
        }

        // 简单的模拟解密：实际项目中可以替换为真实的解密算法
        byte[] decoded = Base64.getDecoder().decode(ciphertext);
        String combined = new String(decoded, StandardCharsets.UTF_8);
        String[] parts = combined.split("\\|");

        if (parts.length == 2 && parts[1].equals(random)) {
            return parts[0];
        }
        return null;
    }

    /**
     * 生成签名
     */
    private static String generateSignature(String plaintext) {
        if (plaintext == null) {
            return null;
        }

        // 使用SM3算法生成签名，与真实环境保持一致
        byte[] hash = Sm3Util.sm3(plaintext.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(hash);
    }

    /**
     * 生成随机字符串
     */
    private static String generateRandomString(int length) {
        String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
        StringBuilder sb = new StringBuilder(length);

        for (int i = 0; i < length; i++) {
            int index = RANDOM.nextInt(characters.length());
            sb.append(characters.charAt(index));
        }

        return sb.toString();
    }

    /**
     * 模拟网络延迟
     */
    private static void simulateNetworkDelay() throws InterruptedException {
        // 随机延迟50-200毫秒，模拟真实网络环境
        long delay = 50 + RANDOM.nextInt(150);
        TimeUnit.MILLISECONDS.sleep(delay);
    }
}

